perm filename GEOM0[3,BGB]1 blob
sn#115096 filedate 1974-08-11 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00010 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 {⊂C<NF3αGEOMED.λ30P28I425,0JCFA} SECTION 3.
C00006 00003
C00011 00004 {JC} FIGURE 3.2 - THE 24 DISPLAYS OF EXAMPLE #2. {I∂65,80X0.152H2
C00015 00005 In example #2, the model of an actual robot arm is read in
C00017 00006 ⊂3.1 Euler Primitives.⊃
C00023 00007
C00027 00008 Example 3 - Make Hexahedron.{λ7W100,1260,0,1900JAF3}
C00029 00009
C00031 00010
C00034 ENDMK
C⊗;
{⊂C;<N;F3;αGEOMED.;λ30;P28;I425,0;JCFA} SECTION 3.
{JCFD} A GEOMETRIC MODELING SYSTEM.
{λ10;W250;JAFA}
3.0 Introduction to GEOMED.
3.1 Euler Primitives.
3.2 Routines using Euler Primitives.
3.3 Euclidean Routines.
3.4 Image Synthesis: Perspective Projection and Clipping.
3.5 Image Analysis: Interface to CRE.
{λ30;W0;I950,0;JUFA}
⊂3.0 Introduction to GEOMED.⊃
GEOMED (Geometric Editor) is a system of subroutines for
manipulating winged edge polyhedra. The system has two
manifestations: first, it appears as an interactive 3-D drawing
program and second, it appears as a geometric modeling command
language. It is the latter manifestation along with some of the
details of implementation that is the subject of this chapter; the
interactive drawing program is documented in [Baumgart 74]. As a
language, GEOMED is all semantics with no particular syntax of its
own; there are about two hundred subroutines which take from zero to
four arguments, return one or no values and which usually have
considerable side effects on the data structures. The subroutines
can be grouped into five classes: utility routines, Euler routines,
Euclidean routines, image synthesis and image analysis routines. The
utility routines include input/output, trigonmetric functions,
memory management, a command scanner and device dependent display
routines; the utility routines will not be further elaborated. The
Euler routines perform topological operations on links, the
Euclidean routines perform geometric computations on data and the
image synthesis routines perform photographic simulations on the
model as a whole. The fifth class, image analysis routines,
consists at present solely of an interface between GEOMED and CRE,
thus the fifth group lacks the completeness of the other parts of the
system.
As in the previous chapter, the programming notation used
will continue to have an ALGOL appearance with specific examples of
actual GEOMED code being given in the language SAIL (Stanford ALGOL)
as is example #1 immediately below. The program in example #1 creates
two cubic prisms and
{λ7;W100;JAF3}
BEGIN "EXAMPLE ONE"
REQUIRE "GEOMES.HDR[GEM,HE]" SOURCE_FILE; COMMENT DECLARE GEOMED EMBEDDED IN SAIL;
DEFINE π="3.1415927";
INTEGER B1,B2,I; COMMENT TWO BODIES AND AN IMAGE COUNTER;
MKUNIV; COMMENT INITIALIZE THE DATA STRUCTURES;
B1 ← MKCUBE(8,1,0.5); COMMENT CREATE A COUPLE OF CUBIC PRISMS;
B2 ← MKCUBE(1,2,4);
TRANSL(B2,-7,1.5,0); COMMENT DISPLACE ONE OF THEM;
FOR I←1 STEP 1 THRU 24 DO COMMENT MAKE 24 IMAGES;
BEGIN
GEODPY; COMMENT DISPLAY REFRESH;
PLOTO("TMP."&CVS(I)); COMMENT OUTPUT LATEST DISPLAY TO DISK;
ROTATE(B1,π/10,π/12,π/13); COMMENT ACTION WITH RESPECT TO ...;
ROTATE(B2,0,2*π/23,0); COMMENT ...WORLD COORDINATES;
END;
END "EXAMPLE ONE";{λ30;W0;JUFA;}
{JC} FIGURE 3.1 - THE 24 DISPLAYS OF EXAMPLE #1.{I∂65,80;X0.152;H2;
*PLTX1.1;I∂0,∂156;*PLTX1.2;I∂0,∂156;*PLTX1.3;I∂0,∂156;*PLTX1.4;I∂0,∂156;
*PLTX1.5;I∂0,∂156;*PLTX1.6;I∂0,∂156;*PLTX1.7;I∂0,∂156;*PLTX1.8;I∂0,∂156;I∂130,80;
*PLTX1.9;I∂0,∂156;*PLTX1.10;I∂0,∂156;*PLTX1.11;I∂0,∂156;*PLTX1.12;I∂0,∂156;
*PLTX1.13;I∂0,∂156;*PLTX1.14;I∂0,∂156;*PLTX1.15;I∂0,∂156;*PLTX1.16;I∂0,∂156;I∂130,80;
*PLTX1.17;I∂0,∂156;*PLTX1.18;I∂0,∂156;*PLTX1.19;I∂0,∂156;*PLTX1.20;I∂0,∂156;
*PLTX1.21;I∂0,∂156;*PLTX1.22;I∂0,∂156;*PLTX1.23;I∂0,∂156;*PLTX1.24;I∂0,∂156;I∂65,0;}
\displays them rotating. The header file,
GEOMES.HDR, is kept on a disk area [GEM,HE] and contains the names
of the necessary load modules, the declarations of all the modeling
routines and SAIL macros for accessing GEOMED data structures. After
the header, the first routine to execute is MKUNIV (make universe),
which initializes the data structures. Next two polyhedra are
created using the MKCUBE routine which takes three arguments: width,
breadth and height for specifying a rectangular right parallelepiped.
All such creation routines return an integer which is the absolute
machine address of the GEOMED node of the entity created. The next
routine used is GEODPY which refreshs the display of the model.
Finally, the example calls TRANSL and ROTATE which perform
translation and rotation. TRANSL takes four argument: first the
thing to be moved followed by the three components of a translation
vector; similarly ROTATE takes four arguments: first the thing to be
moved followed by the three components of a rotation vector;
there are several other ways to specify translation and rotation.
{JC} FIGURE 3.2 - THE 24 DISPLAYS OF EXAMPLE #2. {I∂65,80;X0.152;H2;
*PLTX2.1;I∂0,∂156;*PLTX2.2;I∂0,∂156;*PLTX2.3;I∂0,∂156;*PLTX2.4;I∂0,∂156;
*PLTX2.5;I∂0,∂156;*PLTX2.6;I∂0,∂156;*PLTX2.7;I∂0,∂156;*PLTX2.8;I∂0,∂156;I∂130,80;
*PLTX2.9;I∂0,∂156;*PLTX2.10;I∂0,∂156;*PLTX2.11;I∂0,∂156;*PLTX2.12;I∂0,∂156;
*PLTX2.13;I∂0,∂156;*PLTX2.14;I∂0,∂156;*PLTX2.15;I∂0,∂156;*PLTX2.16;I∂0,∂156;I∂130,80;
*PLTX2.17;I∂0,∂156;*PLTX2.18;I∂0,∂156;*PLTX2.19;I∂0,∂156;*PLTX2.20;I∂0,∂156;
*PLTX2.21;I∂0,∂156;*PLTX2.22;I∂0,∂156;*PLTX2.23;I∂0,∂156;*PLTX2.24;I∂0,∂156;I∂65,0;
λ7;W200;JAF3;}
BEGIN "EXAMPLE TWO"
REQUIRE "GEOMES.HDR[GEM,HE]" SOURCE_FILE; αα GEOMED EMBEDDED IN SAIL;
DEFINE αα="COMMENT"; DEFINE π="3.1415927"; αα DECLARE COMMENT PREFIX;
INTEGER B1,B2,J1,J2,J3,J4,J5,J6,C1,CHR,I;
MKUNIV;GEODPY;
B1 ← INB3D("ARM[DAT,BGB]"); αα MODEL OF THE YELLOW ARM;
B2 ← INB3D("TABLE[DAT,BGB]"); αα MODEL OF THE HAND/EYE TABLE;
J1 ← FDNAME("JOINT1"); αα SHOULDER - ABOUT VERTICAL;
J2 ← FDNAME("JOINT2"); αα ARM - ABOUT HORIZONTAL;
J3 ← FDNAME("JOINT3"); αα SLIDE;
J4 ← FDNAME("JOINT4"); αα WRIST TWIST;
J5 ← FDNAME("JOINT5"); αα WRIST FLAP;
J6 ← FDNAME("JOINT6"); αα HAND;
C1 ← INCAM("ARMCAM[DAT,BGB]"); αα INPUT A PARTICULAR CAMERA MODEL;
FOR I←1 STEP 1 UNTIL 24 DO αα TWENTY FOUR IMAGES FOR FIGURE 3.2;
BEGIN
SHOW2(0,0); αα HIDDEN LINE ELIMINATION DISPLAY REFRESH;
PLOTO("PLTX2."&CVS(I)); αα OUTPUT LATEST DISPLAY FILE TO DISK;
ROTATE(-J1,0,0,π/40); αα ACTION WITH RESPECT TO BODY COORDIATES...;
ROTATE(-J2,0,0,-π/80); αα ...WHEN BODY ARGUMENT IS GIVEN NEGATIVE;
TRANSL(-J3,0,0,0.06);
END;
END "EXAMPLE TWO";{λ30;W0;JUFA;}
In example #2, the model of an actual robot arm is read in
and the first three joints are run through a simulated arm motion.
The routine INB3D reads a B3D polyhedron file from the disk. The arm
was drawn from measurements using the interactive form of GEOMED. The
FDNAME, find name, routine retrieves a body by its print name;
FDNAME returns zero when a name is not found. The routine INCAM reads
in a camera file. Finally, the routine SHOW2 calls the hidden line
eliminator; when SHOW2's arguments are zero, default options are
assumed. The arm model was originally made to illustrate an arm
trajectory for a thesis on arm control [Paul] and has been
used two times since in projects concerning arm trajectory
planning and arm collision avoidance.
GEOMED is a hierarcy of several levels of
routines that are finally invoked by syntactically trivial subroutine
calls. The point illustrated by the examples is that some
applications level GEOMED code has a quite ordinary appearance that
does not require mastery of the many underlying arcane geometric
primitives which are explained in the next several sections.
⊂3.1 Euler Primitives.⊃
The Euler routines of GEOMED are based on the idea that an
arbitrary polyhedron can be created in steps that always maintain the
Euler relation: F-E+V=2*(B-H). Topologically, a simply connected
Eulerian polyhedral graph can be built up with only four creation
primitives: MKBFV, MKEV, MKFE and GLUEE or taken apart with four
kill primitives: KLBFEV, KLEV, KLFE and UNGLUEE. The prefixes "MK"
and "KL", stand for <make> and <kill>; the initials "B", "F", "E"
and "V" invariably stand for <body, face, edge> and <vertex> and
tend to appear in that order. The notion of <GLUE> is associated with
the process of forming (or removing) a handle which increases (or
decreases) the topological genus of the surface by one unit. The
MKBFV primitive takes no arguments and creates a degenerate point
polyhedron of one vertex, one face and one body which is the minimal
non-zero binding satisfying the Euler relation. The MKEV creates a
new edge and a new vertex, the new edge is attached to the old vertex
as a spur in the perimeter of the given face. The MKFE creates a new
face and a new edge, the new edge is placed between the two given
vertices. And the GLUEE routine creates a handle or kills a body node
by placing a new edge between two given vertices and by removing the
second of two given faces. Completing the set, the ESPLIT routine
(explained in section 2.5) is included as a convenient form of MKEV.
In principle, the advantages of the pure Euler primitives are
that they assure valid topology, full generality, reasonable
simplicity and they achieve a semantic level slightly higher than
that of manipulating the polyhedral nodes and links directly.
However, the Euler primitives only satisfy the first of the
conditions defining a solid polyhedron; imposing no particular
restrictions on surface orientation, face/vertex trivalence, face
planarity, face convexity or surface self intersection. Furthermore,
even some low level topological operations (such as body
intersection, chapter 5) are inconvenient to specify in term of the
Euler primitives. Nevertheless in practice, the Euler primitives
perform a useful role as a topological foundation for coding routines
which embody more algebra and geometry and which lead to higher
semantic levels.{|;λ10;JAFA}
BOX 3.1 {JC;T100,200,700;} THE EULER PRIMITIVES.
EULER MAKE PRIMITIVES:
1. BNEW ← MKBFV; Makes point polyhedron.
2. VNEW ← MKEV(F,V); Makes new edge and vertex.
VNEW ← ESPLIT(E); Makes new edge and vertex.
3. ENEW ← MKFE(V1,F,V2); Makes new face and edge.
4. ENEW ← GLUEE(F1,V1,F2,V2); Makes new edge, kills F2;
and makes a hole or kills a body.
EULER KILL PRIMITIVES:
1. QNEW ← KLBFEV(Q); Kills bodies, faces, edge and vertices.
2. FACE ← KLFE(E); Kills E and NFACE(E). Returns PFACE(E).
3. EDGE ← KLEV(V); Kills V and PED(V). Returns other E of V.
VERT ← KLEV(E); Kills E and NVT(E). Returns PVT(E).
4. FNEW ← UNGLUE(E); Kills E, makes F. Returns the new face,
and kills a hole or makes a body.
{|;λ30;T-1;JU;FA}
The remainder of this sub section consists of more
explanation and examples of the Euler primitives and may be skipped
by the reader who does not need an elaboration of this level of
modeling. ~<Non-solid polyhedra>~: Intermediate between Eulerian and
solid polyhedra are the wire, dangling-wire (or spur), lamina,
sheet and wasp-edged polyhedra which are transition states for
creating and altering polyhedral solids. The <wire> polyhedron
consists of one face, N edges and N+1 vertices. A <lamina> is a two
faced polyhedron with no interior edges or dangling wire. A
<dangling wire> or <spur> is made when a MKEV is applied to a vertex
of an already closed simply connected face perimeter; dangling wire
spurs are ultimately "closed" or "tied down" by a MKFE application. A
<sheet> is an array of lamina, with the exception of ruled surfaces of
rotation, commands for folding and manipulating sheets have not been
developed. Finally, a <wasp> polyhedron is a transition state formed by
the GLUEE primitive; this degenerate polyhedron is named for the wasp
waisted face perimeter which (like a spur) is eliminated by
appropriate MKFE applications.
{I∂30,0;FCJC} FIGURE 3.3 - FIVE KINDS OF NON-SOLID POLYHEDRA.{H2;
X0.246;JAFA;I∂0,0;⊗33.1;
I∂0,∂252;⊗33.2;I∂0,∂252;⊗33.3;I∂0,∂252;⊗33.4;I∂0,∂252;⊗33.5;
I∂250,10;}WIRE{I∂0,10+252;}LAMINA{I∂0,10+2*252;}DANGLING WIRE{
I∂0,10+3*252;}SHEET{I∂0,10+4*252;}WASP WAIST{I∂30,0;JUFA}
The use of the Euler primitives is limited to the above
transition states. MKEV sweeps a MKBFV point body into a wire, the
wire may be continued (at only its newest end) by additional MKEV's
until it is closed into a lamina by MKFE'ing the first and last
vertices of the wire. The MKFE is oriented such that if the wire is
planar and the resulting lamina is homogeneous
(non-self-intersecting); then the exterior vector of the newly
created face points into the counter clockwise halfspace of the
lamina, the halfspace from which the generation order of the vertices
appear in counter clockwise order. This particular generation by
Euler sweeping from point, through wire and lamina, to solid is
illustrated by the make hexahedron example #3 and by the somewhat
different make tetrahedron example #5; the final example of this
section, example #5, illustrates the use of GLUEE.
Example 3 - Make Hexahedron.{λ7;W100,1260,0,1900;JAF3}
BEGIN "EXAMPLE THREE"
REQUIRE "GEOMES.HDR[GEM,HE]" SOURCE_FILE; αα GEOMED EMBEDDED IN SAIL;
INTEGER PROCEDURE MAKECUBE(REAL DX,DY,DZ);
BEGIN "MAKECUBE"
INTEGER B,F,E,V1,V2,V3,V4;
DEFINE αα="COMMENT"; αα COMMENT DELIMITER;
αα MAKE RECTANGULAR LAMINA;
B ← MKBFV; F ← PFACE(B); V1 ← PVT(B); αα MAKE POINT POLYHDERA;
XWC(V1) ← DX/2; YWC(V1) ← DY/2; ZWC(V1) ←-DZ/2; αα POSITION FIRST VERTEX;
V2 ← MKEV(F,V1); XWC(V2) ← -DX/2; αα MAKE AND POSITION 2ND VERTEX;
V3 ← MKEV(F,V2); YWC(V3) ← -DY/2; αα MAKE AND POSITION 3RD VERTEX;
V4 ← MKEV(F,V3); XWC(V4) ← DX/2; αα MAKE AND POSITION 4TH VERTEX;
MKFE(V1,F,V4); F ← PFACE(F);
αα MAKE FOUR SPURS ON THE LAMINA;
V1 ← MKEV(F,V1);V2 ← MKEV(F,V2);
V3 ← MKEV(F,V3);V4 ← MKEV(F,V4);
ZWC(V1) ← ZWC(V2) ← ZWC(V3) ← ZWC(V4) ← DZ/2;
αα JOINT SPURS TO FORM FINAL FACE;
MKFE(V1,F,V2); MKFE(V2,F,V3);
MKFE(V3,F,V4); MKFE(V4,F,V1);
RETURN(B);
END "MAKECUBE";
MKUNIV; MAKECUBE(10,8,6);
END "EXAMPLE THREE";{λ30;W0,1260,0,1900;JUFA;Q}
Example 4 - Make Regular Tetrahedron.{λ7;W100;JAF3}
BEGIN "EX4"
REQUIRE "GEOMES.HDR[GEM,HE]" SOURCE_FILE; αα GEOMED EMBEDDED IN SAIL;
DEFINE αα="COMMENT";DEFINE π="3.1415927";
INTEGER PROCEDURE MKTETRA (REAL R); αα MAKE TETRAHEDRON;
BEGIN "MKTETRA"
INTEGER B,F1,F2,V1,V2,V3,V4;
B ← MKBFV; F1 ← PFACE(B); V1 ← PVT(B); αα MAKE POINT POLYHDERA;
XWC(V1) ← ABS(R*0.942809); ZWC(V1) ← -ABS(R/3); αα POSITION FIRST VERTEX;
V2 ← MKEV(F1,V1); ROTATE(V2,0,0,2*π/3); αα MAKE AND POSITION 2ND VERTEX;
V3 ← MKEV(F1,V2); ROTATE(V3,0,0,2*π/3); αα MAKE AND POSITION 3RD VERTEX;
V4 ← MKEV(F1,V3); αα MAKE AND POSITION 4TH VERTEX;
XWC(V4)←YWC(V4)←0;ZWC(V4)←ABS(R);
MKFE(V1,F1,V4); F2 ← PFACE(F1); αα CLOSE SKEW QUADRILATERAL;
MKFE(V1,F1,V3); MKFE(V2,F2,V4);
RETURN(B); αα RETURN THE CREATION;
END "MKTETRA";
MKUNIV; MKTETRA(6); αα INITIALIZE AND TEST MKTETRA;
GEODPY; αα DISPLAY REFRESH;
END "EX4";{λ30;W0,1260,0,1900;JUFA}
Example 5 - Glue two N-edged faces together.{λ7;W100;JAF3}
BEGIN "EXAMPLE FIVE"
REQUIRE "GEOMES.HDR[GEM,HE]" SOURCE_FILE; αα GEOMED EMBEDDED IN SAIL;
DEFINE αα="COMMENT"; DEFINE π="3.1415927";
INTEGER B1,B2; αα TWO TEST CUBES;
INTEGER PROCEDURE GLUEFF(INTEGER FACE1,FACE2); αα DEMO GLUE FACE TO FACE;
BEGIN "GLUEFF"
INTEGER V,V1,V2,E,E0,I; REAL DMIN,D;
V1 ← VCCW(PED(FACE1),FACE1); αα PICK ONE VERTEX OF FACE1;
αα FIND VERTEX OF FACE2 THAT IS CLOSEST TO V1;
DMIN ← 10@10; E ← E0 ← PED(FACE2); αα INITIAL MINIMUMAL DISTANCE;
DO BEGIN
V ← VCCW(E,FACE2);D ← DISTAN(V1,V); αα SCAN FACE2 FOR VERTEX CLOSEST TO V1;
IF Dα<DMIN THEN BEGIN DMIN←D;V2←V;END;
END UNTIL E0 = (E←ECCW(E,FACE2));
αα MAKE THE WASP EDGE;
E ← GLUEE(FACE1,V1,FACE2,V2); αα FACE2 AND BODY ARE KILLED;
αα CLOSE OTHER EDGES;
V ← OTHER(NCCW(E),V1); αα LAST VERTEX, TO STOP SCAN;
DO BEGIN
V1 ← OTHER(PCW(E),V1); αα FETCH NEXT PAIR OF VERTICES;
V2 ← OTHER(PCCW(E),V2);
E ← MKFE(V1,FACE1,V2); αα CLOSE AN EDGE;
END UNTIL V=V1;
RETURN(BGET(E)); αα RETURN THE SURVIVING BODY;
END "GLUEFF";
MKUNIV; αα INITIALIZATION;
B1 ← MKCUBE(2,2,2); B2 ← MKCUBE(3,3,3); αα TWO TEST CUBES;
ROTATE(B1,0,-π/2,0);TRANSL(B1,-3,0,0); αα ORIENT CUBES SO FIRST FACES...;
ROTATE(B2,0,+π/2,0);TRANSL(B2,+4,0,0); αα ...ARE OPPOSITE;
GLUEFF(PFACE(B1),PFACE(B2)); αα TEST THE FUNCTION;
GEODPY; αα DISPLAY REFRESH;
END "EXAMPLE FIVE";{λ30;W0,1260,0,1900;JUFA}